package com.swingson.easydrag;

import com.swingson.easydrag.listeners.DropListener;
import java.awt.Component;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetAdapter;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.io.IOException;
import javax.swing.JComponent;

/**
 * Default dropping target for any drag.
 *
 * @author Mohamed Mansour
 */
public final class DefaultDrop extends DropTargetAdapter {

    protected DropTarget dropTarget;
    protected Component targetComponent;
    private DropListener listener = null;

    /**
     * Constructor for dropping.
     *
     * @param target
     * @param listener
     */
    public DefaultDrop(Component target, DropListener listener) {
        this.targetComponent = target;
        this.listener = listener;
        this.dropTarget = new DropTarget(getComponent(), DnDConstants.ACTION_MOVE,
                this);
        setEnabled(false);
    }

    /**
     * Disable Drop.
     *
     * @param enabled
     */
    public void setEnabled(boolean enabled) {
        dropTarget.setActive(enabled);
    }

    /**
     * Enable Drop.
     *
     * @return
     */
    public boolean isEnabled() {
        return dropTarget.isActive();
    }

    /**
     * The component dropping to.
     *
     * @return
     */
    public Component getComponent() {
        return targetComponent;
    }

    private void setDestinationForSourceComponent(Component source, Component destination) {
        /*Object clientProp=source.getClientProperty("DefaultDragHandler");
         if(clientProp!=null){
         DefaultDrag draghandler=(DefaultDrag) clientProp;
         draghandler.setDestComponent(getComponent());
         }*/
    }

    @Override
    public final void drop(DropTargetDropEvent dtde) {
        if (!dtde.isDataFlavorSupported(GenericTransferable.ITEM_FLAVOR)) {
            dtde.rejectDrop();
            return;
        }

        dtde.acceptDrop(DnDConstants.ACTION_MOVE);

        try {
            Object data = dtde.getTransferable().getTransferData(GenericTransferable.ITEM_FLAVOR);
            JComponent source = (JComponent) dtde.getTransferable().getTransferData(GenericTransferable.SOURCE_COMPONENT_FLAVOR);
            setDestinationForSourceComponent(source, getComponent());
            if (listener.canDrop(source, getComponent(), data, dtde.getLocation().x, dtde.getLocation().y)) {
                listener.performDrop(source, getComponent(), dtde, data);
                dtde.dropComplete(true);
            } else {
                dtde.dropComplete(false);
            }
        } catch (UnsupportedFlavorException | IOException e) {
            dtde.dropComplete(false);
        }
    }

    @Override
    public final void dragOver(DropTargetDragEvent dtde) {
        try {
            JComponent source = (JComponent) dtde.getTransferable().getTransferData(GenericTransferable.SOURCE_COMPONENT_FLAVOR);
            Object item = dtde.getTransferable().getTransferData(GenericTransferable.ITEM_FLAVOR);
            if (listener.canDrop(source, getComponent(), item, dtde.getLocation().x, dtde.getLocation().y)) {
                dtde.acceptDrag(DnDConstants.ACTION_MOVE);
                listener.dragOver(item, dtde.getLocation().x, dtde.getLocation().y);
            } else {
                dtde.rejectDrag();
            }
        } catch (UnsupportedFlavorException | IOException e) {
            dtde.rejectDrag();
        }
    }
}
